package com.kcht.np.controller;

import com.kcht.np.common.jwt.JwtTokenConverter;
import com.kcht.np.service.SysUserService;
import com.kcht.np.service.VerifyCodeService;
import com.kcht.np.util.JsonResult;
import com.kcht.np.vo.TokenValue;
import com.kcht.np.vo.user.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
  * <p>
  * 用户认证 控制器
  * </p>
  *
  * @Package:        com.kcht.np.mp.controller
  * @Description:    用户认证 控制器
  * @Author:         liuqi
  * @CreateDate:     2020/3/31 11:25
 */

@Slf4j
@Api(tags = "[ 权限管理 ] 用户认证")
@RestController
@RequestMapping("/auth")
@SuppressWarnings("all")
public class AuthController {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private JwtTokenConverter jwtTokenConverter;

    @Autowired
    private VerifyCodeService verifyCodeService;

    @ApiOperation(value = "用户登录认证", notes = "用户名，密码登录格式 {\"username\":\"admin\",\"password\":\"admin\"}")
    @PostMapping("/login")
    public JsonResult login(@RequestBody @Validated LoginUser user, BindingResult br) {
        // 根据 CodeKey 从 redis 中获取到 ServerCodeText
        if (!verifyCodeService.checkVerifyCode(user.getCodeKey(), user.getCodeText())) {
            return JsonResult.fail("验证码错误！");
        }
        try {
            String jwtToken = sysUserService.login(user.getUsername(), user.getPassword());
            TokenValue tokenValue = TokenValue.builder()
                    .header(jwtTokenConverter.getTokenHeader())
                    .value(jwtToken)
                    .prefix(jwtTokenConverter.getTokenHead())
                    .expiration(jwtTokenConverter.getExpiration())
                    .build();
            // 登录成功后，就从 redis 中删除验证码
            verifyCodeService.delImgVerifyCode(user.getCodeKey());
            return JsonResult.success("登录成功", tokenValue);
        } catch (AuthenticationException ex) {
            log.error(ex.getMessage());
            return JsonResult.fail("用户名或密码错误");
        }
    }


    @ApiOperation(value = "用户退出登录", notes = "用户退出登录")
    @GetMapping("/logout")
    public JsonResult<TokenValue> logout() {
      try{
          sysUserService.logout();
          return JsonResult.success("退出成功");
      }catch (AuthenticationException e){
          return JsonResult.result(JsonResult.HttpStatus.UNAUTHORIZED.getStatus(), e.getMessage());
      }
    }


    @ApiOperation(value = "刷新Token值", notes = "只需要在请求头中附带token即可")
    @GetMapping("/refresh")
    public JsonResult<TokenValue> refresh(@RequestHeader(value = "${jwt.tokenHeader}") String completeToken) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(principal=="anonymousUser"){
            return JsonResult.result(JsonResult.HttpStatus.UNAUTHORIZED.getStatus(), JsonResult.HttpStatus.UNAUTHORIZED.getValue());
        }else{
            String oldToken = jwtTokenConverter.interceptCompleteToken(completeToken);
            String jwtToken = jwtTokenConverter.refreshToken(oldToken);
            // 封装新的 token 值
            TokenValue tokenValue = TokenValue.builder()
                    .header(jwtTokenConverter.getTokenHeader())
                    .value(jwtToken)
                    .prefix(jwtTokenConverter.getTokenHead())
                    .expiration(jwtTokenConverter.getExpiration())
                    .build();
            return JsonResult.success("刷新token成功！", tokenValue);
        }
    }


    @ApiOperation(value = "获取图形验证码", notes = "获取图形验证码, codeKey 前端传入一个随机生成的字符串",produces = MediaType.IMAGE_JPEG_VALUE)
    @GetMapping(value = "/verify/code/{codeKey}")
    public void imageVerifyCode(@PathVariable String codeKey, HttpServletResponse response) throws IOException {
        // 设置响应的类型格式为图片格式
        response.setContentType("image/jpeg");
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        // 获取 图片 验证码
        ImageIO.write(
                verifyCodeService.generateAndSaveImgVerifyCode(codeKey),
                "JPEG",
                response.getOutputStream()
        );
    }

}
